package com.cmcc.pcap.packet.tcp.tcp.xdr;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.cmcc.pcap.packet.tcp.TcpConnection;
import com.cmcc.pcap.packet.tcp.TcpPacketDecorator;
import com.cmcc.pcap.packet.util.DateUtil;
import com.cmcc.pcap.packet.util.PacketAnalysisConfig;
import com.cmcc.packet.entity.TcpEntity;

import org.pcap4j.packet.Packet;
import org.pcap4j.packet.TcpPacket;

public class TcpXdrGenerate {
	private static Logger logger = LogManager.getLogger(TcpXdrGenerate.class);
	public List<TcpEntity> generate(TcpConnection tcpConnection,String taskId) {
		List<TcpEntity> xdrtcpEntityList = new ArrayList<>();
		//TcpConnection tcpConnection = httpTransaction.tcpConnection;

		logger.debug("this is tcp xdr generate !");
		TcpEntity xdrtcpentity = new TcpEntity();
		xdrtcpentity.setTaskId(Integer.parseInt(taskId));
		xdrtcpentity.setType("TCP");

		ArrayList<TcpPacket> altemp = new ArrayList<>();
		Integer altemp_length = 0;
		for(TcpPacketDecorator tpt:tcpConnection.al){
			if(tpt.tcpPacket.getRawData().length > 0){
				altemp.add(tpt.tcpPacket);
				++altemp_length;
			}
			if(altemp_length == 8)
				break;
		}

		//业务识别
		xdrtcpentity.setTcpPackets(altemp);

		try {
			saveHttpsTcpConnectionToHttpsEntityList(tcpConnection,xdrtcpentity);
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			logger.error(e.getCause(), e);
		}

		//将每个httpEntity加入httpEntityList中，调用SaveHttpTransactionInfo的save方法保存到数据库中
		xdrtcpEntityList.add(xdrtcpentity);

		/**
		 * Interface
		 * ProcedureStartTime
		 * ProcedureEndTime
		 * ProtocolType
		 * AppType
		 * AppSubType
		 * IPAddressType
		 * UserIPv4
		 * UserIPv6
		 * ......
		 *
		 *
		 */
		return xdrtcpEntityList;
	}

	public void saveHttpsTcpConnectionToHttpsEntityList(TcpConnection tcpConnection,TcpEntity xdrtcpentity) throws ParseException{

		int length = tcpConnection.al.size();
		logger.debug("tcpConnection length:"+length);
		
		if(length==0) {
			xdrtcpentity=null;
			return;
		}
			
		TcpPacketDecorator tpdStart = tcpConnection.al.get(0);
		TcpPacketDecorator tpdEnd = tcpConnection.al.get(length-1);

		//计算procedure_start_time
		long timestamp_procedure_start_time = tpdStart.timestamp.getTime();
        Date procedureStartTime = DateUtil.formatTimestamp(timestamp_procedure_start_time);
		xdrtcpentity.setProcedureStartTime(procedureStartTime);

		//计算procedure_end_time
		long timestamp_procedure_end_time = tpdEnd.timestamp.getTime();
        Date procedureEndTime = DateUtil.formatTimestamp(timestamp_procedure_end_time);
		xdrtcpentity.setProcedureEndTime(procedureEndTime);

		//填写interface
		Integer interFace = 11;
		xdrtcpentity.setInterfaceCode(interFace);

		//填写ip_address_type,ipv4是0,ipv6是1
		xdrtcpentity.setIpAddressType(0);

		// 找到连接的connectionKey直接填写源地址和目的地址
        String[] connectionKey = tcpConnection.connectionKey.split("-");
        String[] usersocket = connectionKey[0].split(":");
        String[] serversocket = connectionKey[1].split(":");

        String userIpv4;
        String userIpv6;
        Integer userPort;

        String appServerIpIpv4;
        String appServerIpIpv6;
        Integer appServerPort;

        if(usersocket.length>2) {
        	//填写终端用户的ipv6地址和端口
        	String[] useriplist = Arrays.copyOf(usersocket, usersocket.length-1);
        	userIpv6 = String.join(":", useriplist);
        	userPort =  Integer.valueOf(usersocket[8]);

        	xdrtcpentity.setUserIpv6(userIpv6);
        	xdrtcpentity.setUserPort(userPort);

        	// 填写ip_address_type,ipv4是0,ipv6是1
        	xdrtcpentity.setIpAddressType(1);

        }
        else {
        	//填写终端用户的ipv4地址和端口
        	userIpv4 = usersocket[0];
        	userIpv4 = userIpv4.replace("/", "");
        	userPort = Integer.valueOf(usersocket[1]);

        	xdrtcpentity.setUserIpv4(userIpv4);
        	xdrtcpentity.setUserPort(userPort);

        	// 填写ip_address_type,ipv4是0,ipv6是1
        	xdrtcpentity.setIpAddressType(0);

        }


        // 填写L4 Protocol,0为tcp,1为udp
        xdrtcpentity.setL4Protocal(0);

        if(serversocket.length>2) {
        	//填写服务端用户的ipv6地址和端口
        	String[] appserveriplist = Arrays.copyOf(serversocket, serversocket.length-1);
        	appServerIpIpv6 = String.join(":", appserveriplist);
        	appServerPort =  Integer.valueOf(serversocket[8]);

        	xdrtcpentity.setAppServerIpIpv6(appServerIpIpv6);
        	xdrtcpentity.setAppServerPort(appServerPort);
        }
        else {
        	//填写服务端用户的ipv4地址和端口
        	appServerIpIpv4 = serversocket[0];
        	appServerIpIpv4 = appServerIpIpv4.replace("/", "");
        	appServerPort = Integer.valueOf(serversocket[1]);

        	xdrtcpentity.setAppServerIpIpv4(appServerIpIpv4);
        	xdrtcpentity.setAppServerPort(appServerPort);
        }
        //填写payload
        //控制拿到payload的报文个数
        /*
         * TODO
         */
        Integer payloadNum = PacketAnalysisConfig.getConfigAsInt("tcp.payloads.num");
        byte[] payloads = new byte[]{};

        /*
         * 根据配置文件，控制拿payload的个数
         */
		Integer getPayloadLength = 0;
        if(payloadNum < tcpConnection.al.size())
        	getPayloadLength = payloadNum;
        else
        	getPayloadLength = tcpConnection.al.size();

		Integer allength = tcpConnection.al.size();
		Integer p=0;
        while(getPayloadLength>0 && p<allength){
        	Packet payloadPacket = tcpConnection.al.get(p).tcpPacket.getPayload();
        	if(payloadPacket !=null){
        		byte[] temp = payloadPacket.getRawData();
				byte[] c = new byte[payloads.length+temp.length];
				System.arraycopy(payloads, 0, c, 0, payloads.length);
				System.arraycopy(temp, 0, c, payloads.length, temp.length);
				payloads = c;
				getPayloadLength--;
				p++;
			}
        	else{
        		p++;
			}

		}
		//将二进制数组转为16进制字符串
		StringBuilder payloadstr = new StringBuilder(payloads.length*2);
		for(byte b:payloads){
			payloadstr.append(String.format("%02x",new Integer(b & 0xff)));
		}
        xdrtcpentity.setPayload(payloadstr);
        xdrtcpentity.setPayloadLength(payloadstr.length());


	}
}